define(async () => {
    const [config, env, util, libs] = await require("config", "libs/env", "libs/util", "libs/libs");
    const { Frame } = libs;

    const canvas = document.getElementById("canvas");   
    const offscreenCanvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    const oCtx = offscreenCanvas.getContext("2d");

    canvas.width = config.displayWidth;
    canvas.height = config.displayHeight;
    offscreenCanvas.width = config.displayWidth;
    offscreenCanvas.height = config.displayHeight;
    canvasZoom(env.window.width, env.window.height);

    let currentFrame = null;
    let lastTimestamp = 0;

    function render() {
        if(!currentFrame)
            return;
        // oCtx.clearRect(0, 0, canvas.width, canvas.height);
        oCtx.clearRect(0, 0, canvas.width, canvas.height);
        currentFrame.render(oCtx);
        // oCtx.globalAlpha = data.alpha;
        // oCtx.drawImage(data.image, data.x, data.y, data.w, data.h);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(offscreenCanvas, 0, 0);
        lastTimestamp = Date.now();
    }

    (function loop() {
        render();
        window.requestAnimationFrame(loop);
    })();

    function canvasZoom(windowWidth, windowHeight) {
        let canvasScale = 1;
        if(windowWidth > config.displayWidth) {
            if(windowHeight < config.displayHeight)
                canvasScale = parseFloat((windowHeight / config.displayHeight).toFixed(3));
        }
        else {
            canvasScale = parseFloat((windowWidth / config.displayWidth).toFixed(3));
            if(windowHeight < config.displayHeight)
                canvasScale = Math.min(canvasScale, parseFloat((windowHeight / config.displayHeight).toFixed(3)));
        }
        canvas.style.transform = `scale(${canvasScale})`;
        offscreenCanvas.style.transform = `scale(${canvasScale})`;
    }

    function setFrame(frame) {
        util.assert(frame instanceof Frame, "param type must be Frame");
        currentFrame = frame;
    }

    window.onresize = () => canvasZoom(env.window.width, env.window.height);

    return {
        setFrame
    };
});